/**
 * 导出组件
 */
import React, { Component } from 'react';
import { Button, Modal, Checkbox } from 'antd';
import axios from 'axios';
import { appKey, api } from '../configs/config';
import { download } from '../utils/browser';
import services, { api as apiPaths } from '../services/export';
import Pc from './permissionControl';

const styles = {
	main: {
		display: 'inline'
	},
	but: {
		marginRight: '1em'
	}
};

const itemChangeFun = {};

// 获取localStorage的key
export function getKey(title) {
	return `${title}__export`;
}

// 保存到localStorage
export function setItem(title, value) {
	if (itemChangeFun[title]) itemChangeFun[title].forEach(fun => fun(value));
	window.localStorage.setItem(getKey(title), JSON.stringify(value));
}

// 获取已保存的
export function getItem(title) {
	const saveKeys = window.localStorage.getItem(getKey(title));
	return saveKeys ? JSON.parse(saveKeys) : [];
}

// 监听保存事件
export function onSetItem(title, callback) {
	itemChangeFun[title] = itemChangeFun[title] || [];
	itemChangeFun[title].push(callback);
}

// 取消监听
export function offSetItem(title, callback) {
	itemChangeFun[title] = itemChangeFun[title] || [];
	itemChangeFun[title] = itemChangeFun[title].filter(f => f !== callback);
}

export function getColumns(columns, tableDisplay, keys) {
	let showKeys = null;
	if (!tableDisplay) {
		showKeys = keys;
		if (!showKeys || !showKeys.length) return columns;
	} else {
		showKeys = (keys && keys.length) ? tableDisplay.filter(k => keys.includes(k)) : tableDisplay;
	}
	return columns.filter(c => (!c.dataIndex && c.render) || showKeys.includes(c.dataIndex));
}

// 装饰器，给组件添加监听保存事件和取消监听
export function onSetItemDecorator(target) {
	const stateKey = 'showKeys';// 在state中的key名
	const { componentWillMount, componentWillUnmount } = target.prototype;
	target.prototype.componentWillMount = function () {
		const { exportTitle } = this.props;
		if (componentWillMount) componentWillMount.call(this);
		if (this.state) {
			this.state[stateKey] = getItem(exportTitle);
		} else {
			this.state = {
				[stateKey]: getItem(exportTitle)
			};
		}
		this.onSetItem = this.onSetItem.bind(this);
		onSetItem(exportTitle, this.onSetItem);
	};

	target.prototype.componentWillUnmount = function () {
		if (componentWillUnmount) componentWillUnmount.call(this);
		const { exportTitle } = this.props;
		offSetItem(exportTitle, this.onSetItem);
	};

	target.prototype.onSetItem = function (keys) {
		this.setState({ [stateKey]: keys });
	};

	target.prototype.getColumns = function (columns, display) {
		const { tableDisplay } = this.props;
		const keys = this.state[stateKey];
		return getColumns(columns, display || tableDisplay, keys);
	};
}

class Export extends Component {

	constructor(props, context) {
		super(props, context);

		this.saveKeys = getItem(props.title);
		this.state = {
			titleModal: false,
			selectedKeys: this.saveKeys,
			exporting: false,
			expored: 0
		};
	}

	select = key => {
		const { selectedKeys } = this.state;
		if (selectedKeys.includes(key)) {
			this.setState({
				selectedKeys: selectedKeys.filter(k => k !== key)
			});
		} else {
			this.setState({
				selectedKeys: selectedKeys.concat(key)
			});
		}
	}

	saveTitle = () => {
		const { selectedKeys } = this.state;
		const { title } = this.props;
		setItem(title, selectedKeys);
		this.saveKeys = selectedKeys.concat();
		this.setState({ titleModal: false });
		if (this.waitingExport) {
			this.exportData();
		}
	}

	exportData = async () => {
		const { queryData, ids, columns, title, status } = this.props;
		const { selectedKeys } = this.state;
		if (title === 'refundExport' && (status !== this.state.different)) {
			localStorage.removeItem('refundExport__export');
			this.waitingExport = true;
			await this.setState({
				selectedKeys: [],
				different: status,
				titleModal: true
			});
			return;
		}
		if (!selectedKeys || !selectedKeys.length) {
			this.setState({ titleModal: true });
			this.waitingExport = true;
			return;
		}
		this.waitingExport = false;
		this.setState({ exporting: true, expored: 0 });
		const properties = [];
		const titles = selectedKeys.map(k => {
			const t = columns.find(c => c.dataIndex === k);
			properties.push(t.prefix ? `${t.prefix}.${k}` : k);
			return t.title;
		});
		const res = await services[title](
			{
				ids,
				query: queryData,
				properties,
				titles
			},
			e => {
				this.setState({ expored: parseInt(e.loaded / 1024) });
			}
		);
		this.setState({ exporting: false, expored: 0 });
		download(res.data, `${title}.xls`);
	}

	render() {
		const { columns, mode, title, custom = true, tableDisplay } = this.props;
		const { titleModal, selectedKeys, exporting, expored } = this.state;
		return (
			<Pc url={apiPaths[title]}>
				<div style={styles.main}>
					{
						mode !== 'customize' ? (
							<Button
								icon="download"
								className="opt-but"
								onClick={this.exportData}
								style={styles.but}
							>
								{exporting ? `导出中...${expored}k` : '导出'}
							</Button>
						) : null
					}
					{custom &&
						<Button
							icon="bars"
							className="opt-but"
							onClick={() => this.setState({ titleModal: true })}
							style={styles.but}
						>
							自定义
						</Button>}
					<Modal
						title="自定义列表"
						visible={titleModal}
						onOk={this.saveTitle}
						onCancel={() => this.setState({ titleModal: false, selectedKeys: this.saveKeys })}
					>
						{(tableDisplay ? getColumns(columns, tableDisplay) : columns).filter(c => c.dataIndex && c.dataIndex !== 'opt' && c.dataIndex !== 'index').map(c => (
							<Checkbox onChange={() => this.select(c.dataIndex)} checked={selectedKeys.includes(c.dataIndex)}>
								{c.title}
							</Checkbox>
						))}
					</Modal>
				</div>
			</Pc>
		);
	}
}

export default Export;
